home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000 #2
/
Ham Radio 2000 - Volume 2.iso
/
HAMV2
/
TCP_IP
/
TNOS230S
/
TERM.C
< prev
next >
Wrap
C/C++ Source or Header
|
1997-05-24
|
7KB
|
299 lines
/* TERM server: access a local asy device from a tcp connection.
* Copyright 1991 Phil Karn, KA9Q
* Adapted from KA9Q's NOS 930622 by N5KNX 11/95.
*/
#include "global.h"
#ifdef TERMSERVER
#include "commands.h"
#include "netuser.h"
#include "smtp.h"
#include "iface.h"
#include "hardware.h"
#include "mailbox.h"
#include "asy.h"
#ifdef UNIX
#include "unixasy.h"
#else
#include "n8250.h"
#endif
#include "devparam.h"
#ifndef MSDOS
#include "telnet.h"
#endif
#if !defined(_lint)
static char rcsid[] OPTIONAL = "$Id: term.c,v 1.12 1997/05/24 13:11:12 root Exp root $";
#endif
static void termserv (int s,void *unused,void *p);
static void termrx (int s,void *p1,void *p2);
static int prompting_read (const char *prompt, int s, char *buf, int buflen);
static const char termlistener[] = "TERM listener";
static const char termserver[] = "TERM server";
static int S_term = -1;
static char *Termpass = NULLCHAR;
struct portlist {
char *portname;
struct portlist *next;
};
#define NULLPL (struct portlist *)NULL
static struct portlist *Termports = NULLPL;
/* Start up TCP term server */
int
term1 (argc, argv, p)
int argc;
char *argv[];
void *p OPTIONAL;
{
int port = IPPORT_TERM;
if (argc > 1) {
port = atoi (argv[1]);
tprintf ("Starting Term Server on port %d\n", port);
}
return (installserver (argc, argv, &S_term, termlistener, port,
INADDR_ANY, termserver, termserv, 512, NULL));
}
/* Stop term server */
int
term0 (argc, argv, p)
int argc OPTIONAL;
char *argv[] OPTIONAL;
void *p OPTIONAL;
{
return (deleteserver (&S_term));
}
static void
termserv(s,unused,p)
int s;
void *unused OPTIONAL;
void *p OPTIONAL;
{
char buf[64];
struct iface *ifp = NULLIF;
struct route *rp;
struct sockaddr_in fsocket;
struct proc *rxproc = NULLPROC;
struct asy *ap = (struct asy *) 0;
struct mbuf *bp;
struct portlist *pl;
int (*rawsave) (struct iface *,struct mbuf *) = NULLFP((struct iface*,struct mbuf*));
int i, saved = 0;
(void) sockmode (s, SOCK_BINARY);
(void) sockowner (s, Curproc);
close_s (Curproc->output);
close_s (Curproc->input);
Curproc->output = Curproc->input = s;
(void) setflush (s, '\n');
log (s, "open term");
/* Prompt for and check remote password */
if (Termpass) {
if (prompting_read ("Password: ", s, buf, sizeof(buf)) < 0)
goto quit;
rip (buf);
if (strcmp (buf, Termpass) != 0) {
tputs ("Login incorrect\n");
goto quit;
}
}
/* Prompt for desired interface. Verify that it exists, that
* we're not using it for our TCP connection, that it's an
* asynch port, and that there isn't already another tip, term
* or dialer session active on it.
*/
for ( ; ; ) {
if (prompting_read ("Interface: ", s, buf, sizeof(buf)) < 0)
goto quit;
rip (buf);
if ((ifp = if_lookup (buf)) == NULLIF) {
tprintf (Badinterface, buf);
continue;
}
for (pl = Termports; pl; pl = pl->next)
if (!strcmp (pl->portname, buf))
break;
if (!pl) {
tprintf (Badinterface, buf);
continue;
}
if (getpeername(s,(char *)&fsocket,&i) != -1
&& !ismyaddr(fsocket.sin_addr.s_addr)
&& (rp = rt_lookup(fsocket.sin_addr.s_addr)) != NULLROUTE
&& rp->iface == ifp) {
tprintf ("You're using interface %s!\n", ifp->name);
continue;
}
ap = &Asy[ifp->dev];
if (ifp->dev >= ASY_MAX || ap->iface != ifp ) {
tprintf ("Interface %s not asy port\n", buf);
continue;
}
if (ifp->raw == bitbucket) {
tprintf("%s already in use\n", buf);
continue;
}
/* Save output handler and temporarily redirect output to null */
rawsave = ifp->raw;
ifp->raw = bitbucket;
saved = 1;
/* Suspend the packet input driver. Note that the transmit driver
* is left running since we use it to send buffers to the line.
*/
suspend (ifp->rxproc);
#ifdef POLLEDKISS
suspend (ap->poller);
#endif
break;
}
if (prompting_read ("Wink DTR? ", s, buf, sizeof(buf)) < 0)
goto quit;
if (buf[0] == 'y' || buf[0] == 'Y') {
(void) asy_ioctl (ifp, PARAM_DTR, 1, 0); /* drop DTR */
(void) kpause (1000L);
(void) asy_ioctl (ifp, PARAM_DTR, 1, 1); /* raise DTR */
}
if (prompting_read ("Turn off local echo? ", s, buf, sizeof(buf)) < 0)
goto quit;
if (buf[0] == 'y' || buf[0] == 'Y')
tprintf ("%c%c%c%c%c%c", IAC, WILL, TN_ECHO, IAC, WILL, TN_SUPPRESS_GA);
/* Now fork into receive and transmit processes */
rxproc = newproc ("term rx", 270, termrx, s, ifp, NULL, 0);
/* We continue to handle the TCP->asy direction */
while ((i = recvchar (s)) != EOF) {
while (i == IAC) {
i = recvchar (s); /* DO/DONT/WILL/WONT */
if (i == IAC)
break; /* escaped IAC */
i = recvchar (s); /* opt */
i = recvchar (s);
}
if (i == '\n')
i = '\r'; /* NL => CR */
bp = pushdown (NULLBUF, 1);
#if 1
bp->data[0] = (unsigned char) i;
#else
bp->data[0] = (i & 0x7f);
#endif
(void) asy_send (ifp->dev,bp);
ifp->lastsent = secclock();
if (i == '\r')
kwait(NULL); /* give output buffers a chance to empty */
}
quit:
if (saved) {
killproc (rxproc);
if (ifp) {
ifp->raw = rawsave;
resume (ifp->rxproc);
}
#ifdef POLLEDKISS
if (ap)
resume (ap->poller);
#endif
}
log (s, "close term");
Curproc->input = -1; /* avoid closing s twice */
}
static void
termrx (s, p1, p2)
int s;
void *p1;
void *p2 OPTIONAL;
{
int c;
struct iface *ifp = (struct iface *)p1;
while ((c = get_asy (ifp->dev)) != EOF) {
#if 1
(void) usputc (s, uchar(c));
#else
usputc (s, c & 0x7f);
#endif
usflush (s);
}
}
static int
prompting_read (prompt, s, buf, buflen)
const char *prompt;
int s, buflen;
char *buf;
{
int nread;
if (prompt) {
(void) usputs (s, prompt);
usflush (s);
}
nread = recvline (s, (unsigned char *) buf, (unsigned) buflen);
return nread;
}
int
doterm (argc, argv, p)
int argc;
char *argv[];
void *p OPTIONAL;
{
int i;
struct portlist *pl, *pnext;
if (argc == 1)
usage:
tputs ("Usage: term ports [portlist] | term password pwstring\n");
else if (!strcmp( argv[1], "ports")) {
if (argc == 2) {
tputs ("term ports: ");
for (pl = Termports; pl; pl = pl->next)
tprintf ("%s ", pl->portname);
tputc ('\n');
} else {
for (pl = Termports; pl; pl = pnext) {
free (pl->portname);
pnext = pl->next;
free (pl);
}
Termports = NULLPL;
for (i = 2; i < argc; i++) {
pl = mallocw (sizeof (struct portlist));
pl->portname = strdup (argv[i]);
pl->next = Termports;
Termports = pl;
}
}
} else if (!strncmp (argv[1], "pass", 4)) {
if (argc != 3)
goto usage;
free (Termpass);
Termpass = strdup (argv[2]);
} else
goto usage;
return 0;
}
#endif /* TERMSERVER */